package com.hhit.zhgd.task

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.hhit.zhgd.domain.entity.ZhgdCronJob
import com.hhit.zhgd.service.ZhgdCronJobService
import com.hhit.zhgd.task.factory.AutowiringSpringBeanJobFactory
import jakarta.annotation.PostConstruct
import org.quartz.*
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

@Component
class JobScheduler {
    private val log = LoggerFactory.getLogger(JobScheduler::class.java)

    @Autowired
    private var scheduler: Scheduler? = null

    @Autowired
    private var zhgdCronJobService: ZhgdCronJobService? = null

    @Autowired
    private var jobFactory: AutowiringSpringBeanJobFactory? = null

    @PostConstruct
    fun init() {
        scheduler?.setJobFactory(jobFactory)
        try {
            loadJobsFromDatabase()
        } catch (e: Exception) {
            log.error("Error loading jobs from database: ${e.message}")
        }
    }

    private fun loadJobsFromDatabase() {
        val queryWrapper = QueryWrapper<ZhgdCronJob>()
        queryWrapper.eq("status", 1)
        val jobs: List<ZhgdCronJob>? =
            zhgdCronJobService?.list(queryWrapper)
        jobs?.forEach { job -> scheduleJob(job) }
    }

    private fun scheduleJob(job: ZhgdCronJob) {
        try {
            val jobDetail: JobDetail = JobBuilder.newJob(Class.forName(job.taskClass) as Class<out Job?>)
                .withIdentity(job.taskName)
                .build()
            val trigger: CronTrigger = TriggerBuilder.newTrigger()
                .withIdentity(job.taskName + "Trigger")
                .withSchedule(CronScheduleBuilder.cronSchedule(job.cronExpression))
                .build()
            scheduler!!.scheduleJob(jobDetail, trigger)
        } catch (e: SchedulerException) {
            e.printStackTrace()
        } catch (e: ClassNotFoundException) {
            e.printStackTrace()
        }
    }


    @Throws(SchedulerException::class)
    fun updateTaskCronExpression(taskName: String, newCronExpression: String?) {
        if (!CronExpression.isValidExpression(newCronExpression)) {
            throw RuntimeException(String.format("该cron表达式:%s格式不正确", newCronExpression))
        }
        if (!scheduler!!.checkExists(JobKey(taskName))) {
            throw RuntimeException(String.format("该定时任务:%s已不存在", taskName))
        }
        val one = zhgdCronJobService!!.getOne(
            QueryWrapper<ZhgdCronJob?>().eq("task_name",taskName).last("limit 1")
        )
        if (one!=null) {
            one?.cronExpression = newCronExpression
            zhgdCronJobService?.updateById(one)
            val triggerKey = TriggerKey(taskName + "Trigger")
            val oldTrigger = scheduler!!.getTrigger(triggerKey) as CronTrigger
            if (oldTrigger != null) {
                val triggerBuilder = oldTrigger.triggerBuilder
                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(newCronExpression))
                val newTrigger = triggerBuilder.build()
                scheduler?.rescheduleJob(triggerKey, newTrigger)
            }
        } else {
            throw RuntimeException(String.format("未找到该定时任务:%s的任务信息", taskName))
        }
    }

    @Throws(SchedulerException::class)
    fun pauseTask(taskName: String?) {
        val jobKey = JobKey(taskName)
        if (scheduler?.checkExists(jobKey)==true) {
            scheduler?.pauseJob(jobKey)
        } else {
            throw RuntimeException(String.format("该定时任务:%s已不存在", taskName))
        }
    }

    @Throws(SchedulerException::class)
    fun stopTask(taskName: String?) {
        if (scheduler?.checkExists(JobKey(taskName))==false) {
            throw RuntimeException(String.format("该定时任务:%s已不存在", taskName))
        }
        val one = zhgdCronJobService?.getOne(
            QueryWrapper<ZhgdCronJob>().eq("task_name", taskName).last("limit 1")
        )
        if (one!=null) {
            one.status = 2
            zhgdCronJobService?.updateById(one)
            // 需要在Quartz中暂停相应的触发器（Triggers）。这样可以确保即使触发器的状态被暂停，任务也不会被触发执行
            val triggerKey = TriggerKey(taskName)
            scheduler!!.pauseTrigger(triggerKey)
            // 检查作业状态并终止正在执行的作业
            val jobDetail = scheduler?.getJobDetail(JobKey.jobKey(taskName))
            if (jobDetail != null) {
                // 判断作业是否正在执行
                if (scheduler!!.currentlyExecutingJobs.stream()
                        .anyMatch { jobExecutionContext: JobExecutionContext ->
                            jobExecutionContext.jobDetail.key == jobDetail.key
                        }
                ) {
                    // 终止正在执行的作业
                    scheduler?.interrupt(jobDetail.key)
                }
                scheduler?.deleteJob(jobDetail.key)
            }
        } else {
            throw RuntimeException(String.format("未找到该定时任务:%s的任务信息", taskName))
        }
    }

    @Throws(SchedulerException::class)
    fun resumeTask(taskName: String?) {
        val jobKey = JobKey(taskName)
        if (scheduler?.checkExists(jobKey)==true) {
            scheduler?.resumeJob(jobKey)
        } else {
            throw RuntimeException(String.format("该定时任务:%s已不存在", taskName))
        }
    }


}